import { ref, defineComponent, Ref, watch, computed } from 'vue';
import {
  getSpanProps,
  useFocusAndBlur,
  useNamespace,
} from '@ibiz-template/vue3-util';
import dayjs from 'dayjs';
import './span.scss';
import { CodeListItem } from '@ibiz-template/runtime';
import { SpanEditorController } from '../span-editor.controller';

export const IBizSpan = defineComponent({
  name: 'IBizSpan',
  props: getSpanProps<SpanEditorController>(),
  setup(props, { emit }) {
    const ns = useNamespace('span');

    const c = props.controller;

    const text: Ref<string> = ref('');

    const codeList = c.codeList;
    // 值分隔符
    let valueSeparator = ',';
    if (codeList && codeList.valueSeparator) {
      valueSeparator = codeList.valueSeparator;
    }

    watch(
      () => props.value,
      (newVal, oldVal) => {
        if (newVal !== oldVal) {
          if (!newVal) {
            text.value = '';
            return;
          }
          if (c.parent.valueFormat) {
            text.value = dayjs(newVal).format(c.parent.valueFormat);
          } else {
            text.value = newVal ? `${newVal}` : '';
          }
          if (c.parent.unitName) {
            text.value += c.parent.unitName;
          }
        }
      },
      {
        immediate: true,
      },
    );

    // 代码表数据
    const items = ref<readonly CodeListItem[]>([]);
    if (codeList) {
      watch(
        () => props.data,
        newVal => {
          c.loadCodeList(newVal).then(_codeList => {
            items.value = _codeList;
          });
        },
        {
          immediate: true,
          deep: true,
        },
      );
    }

    // 代码表转换后文本
    const codeListText = computed(() => {
      if (!codeList || !props.value || items.value.length === 0) {
        return undefined;
      }
      if (codeList.codeItemValueNumber) {
        return items.value.find(item => item.value === props.value)?.text;
      }
      const values = (props.value as string).toString().split(valueSeparator);
      const selects = items.value.filter(item =>
        values.includes(item.value as string & number),
      );
      return selects.map(item => item.text).join(valueSeparator);
    });

    // 聚焦失焦事件
    const { componentRef: editorRef } = useFocusAndBlur(
      () => emit('focus'),
      () => emit('blur'),
    );

    return {
      ns,
      text,
      codeListText,
      editorRef,
    };
  },
  render() {
    return (
      <span
        class={[this.ns.b(), this.readonly ? this.ns.m('readonly') : '']}
        ref='editorRef'
      >
        {this.codeListText || this.text}
      </span>
    );
  },
});
